﻿using System;
using System.Data;
using System.Configuration;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.Services.Protocols;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;

/// <summary>
/// Summary description for crmActions
/// http://blog.customereffective.com/blog/2009/06/crm-helper-class-for-custom-isv-aspx-pages.html
/// </summary>
/// 
namespace icrmGridActions
{
  public class crmActions
  {
    CrmService _crmService = new CrmService();
    //CrmService _crmService = new CrmService();
    string _crmServerUrl;
    string _orgName;
    bool IFD = false;  //Indicates if IFD
    HttpContext _context;
    string _crmurl;
    bool _offline;

    public crmActions(bool offline, string orgname, string crmurl, Uri currentURL, HttpContext context)
    {
      _offline = offline;
      _orgName = orgname;
      _context = context;
      if (crmurl.Equals("http://i-worx-crm-02/MSCRMServices/2007/CrmService.asmx",StringComparison.OrdinalIgnoreCase))
        _crmurl = "http://localhost/MSCRMServices/2007/CrmService.asmx";
      else
        _crmurl = crmurl;
      _crmServerUrl = String.Format("{0}://{1}:{2}", currentURL.Scheme, currentURL.Host, currentURL.Port);
      UriBuilder test = new UriBuilder(crmurl);
      if (test.Host != currentURL.Host)
        IFD = true;
      using (new CrmImpersonator())
      {
        CrmAuthenticationToken token;
        if (offline == true)
        {
          token = new CrmAuthenticationToken();
        }
        else
        {
          // Notice that the Context parameter value is Page.Context.
          token = CrmAuthenticationToken.ExtractCrmAuthenticationToken(context, orgname);
        }
        token.OrganizationName = orgname;
        token.AuthenticationType = 0;

        //Create the Service
        _crmService = new CrmService();
        _crmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
        _crmService.CrmAuthenticationTokenValue = token;
        _crmService.Url = _crmurl;
      }
    }

    public void CompleteActivites(string[] selectedEntities)
    {
      int errLine = 0;
      string errID = "";
      try
      {
        //using (new CrmImpersonator())
        //{
        //  CrmAuthenticationToken token;
        //  if (_offline == true)
        //  {
        //    token = new CrmAuthenticationToken();
        //  }
        //  else
        //  {
        //    // Notice that the Context parameter value is Page.Context.
        //    token = CrmAuthenticationToken.ExtractCrmAuthenticationToken(_context, _orgName);
        //  }
        //  token.OrganizationName = _orgName;
        //  if (IFD)
        //    token.AuthenticationType = 2;
        //  else
        //    token.AuthenticationType = 0;

        //  //Create the Service
        //  _crmService = new CrmService();
        //  _crmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
        //  _crmService.CrmAuthenticationTokenValue = token;
        //  _crmService.Url = _crmurl;
        errLine = 20;
        for (int i = 0; i < selectedEntities.Length; i++)
        {
          // Set a temporary GUID to the ID in the string array.
          System.Guid idGuid = new System.Guid(selectedEntities[i]);
          errID = idGuid.ToString();
          // Specify the database columns (entity attributes) that are to be retrieved. 
          errLine = 30 + i;
          ColumnSet cols = new ColumnSet();
          //cols.Attributes = new string[] { "activityid", "activitytypecode", "statecode" };
          cols.AddColumns(new string[] { "activityid", "activitytypecode", "statecode" });
          errLine = 40 + i;
          // Retrieve the contact data from CRM
          string activityType = "";
          bool opened = false;
          try
          {
            activitypointer actPointer = (activitypointer)_crmService.Retrieve(EntityName.activitypointer.ToString(), idGuid, cols);
            activityType = actPointer.activitytypecode.Value;
            opened = (actPointer.statecode.Value.Equals(ActivityPointerState.Open) || actPointer.statecode.Value.Equals(ActivityPointerState.Scheduled));
          }
          catch
          {
            errLine = 140 + i;
            TargetRetrieveDynamic target = new TargetRetrieveDynamic();
            target.EntityName = EntityName.activitypointer.ToString();
            target.EntityId = new System.Guid(selectedEntities[i]);
            RetrieveRequest request = new RetrieveRequest();
            request.Target = target;
            request.ColumnSet = cols;// new AllColumns();
            request.ReturnDynamicEntities = true;
            errLine = 240 + i;
            RetrieveResponse response = (RetrieveResponse)_crmService.Execute(request);
            errLine = 340 + i;
            DynamicEntity de = (DynamicEntity)response.BusinessEntity;
            errLine = 440 + i;
            EntityNameReference entityNamePro = (EntityNameReference)de.Properties["activitytypecode"];
            errLine = 540 + i;
            activityType = entityNamePro.Value;
            errLine = 640 + i;
            string stateProp = (string)de.Properties["statecode"];
            opened = (stateProp == ActivityPointerState.Open.ToString() || stateProp == ActivityPointerState.Scheduled.ToString());
          }
          errLine = 50 + i;
          //if (actPointer.statecode.Value.Equals(ActivityPointerState.Open) || actPointer.statecode.Value.Equals(ActivityPointerState.Scheduled))
          if (opened)
          {
            //if (!(actPointer.activitytypecode.IsNull & actPointer.activitytypecode.IsNullSpecified))
            //{
            //string activityType = actPointer.activitytypecode.Value;
            if (activityType.Equals(EntityName.task.ToString()))
            {
              SetStateTaskRequest stateTask = new SetStateTaskRequest();
              stateTask.EntityId = idGuid;
              stateTask.TaskState = TaskState.Completed;
              stateTask.TaskStatus = -1;
              errLine = 60 + i;
              _crmService.Execute(stateTask);
              errLine = 70 + i;
            }
            else if (activityType.Equals(EntityName.appointment.ToString()))
            {

              SetStateAppointmentRequest stateApp = new SetStateAppointmentRequest();
              stateApp.EntityId = idGuid;
              stateApp.AppointmentState = AppointmentState.Completed;
              stateApp.AppointmentStatus = -1;
              _crmService.Execute(stateApp);
            }
            else if (activityType.Equals(EntityName.email.ToString()))
            {
              SetStateEmailRequest stateEmail = new SetStateEmailRequest();
              stateEmail.EntityId = idGuid;
              stateEmail.EmailState = EmailState.Completed;
              stateEmail.EmailStatus = -1;
              _crmService.Execute(stateEmail);
            }
            else if (activityType.Equals(EntityName.fax.ToString()))
            {
              SetStateFaxRequest stateFax = new SetStateFaxRequest();
              stateFax.EntityId = idGuid;
              stateFax.FaxState = FaxState.Completed;
              stateFax.FaxStatus = -1;
              _crmService.Execute(stateFax);
            }
            else if (activityType.Equals(EntityName.letter.ToString()))
            {
              SetStateLetterRequest stateLetter = new SetStateLetterRequest();
              stateLetter.EntityId = idGuid;
              stateLetter.LetterState = LetterState.Completed;
              stateLetter.LetterStatus = -1;
              _crmService.Execute(stateLetter);
            }
            else if (activityType.Equals(EntityName.phonecall.ToString()))
            {
              SetStatePhoneCallRequest statePhone = new SetStatePhoneCallRequest();
              statePhone.EntityId = idGuid;
              statePhone.PhoneCallState = PhoneCallState.Completed;
              statePhone.PhoneCallStatus = -1;
              _crmService.Execute(statePhone);

            }
            //}
          }
        }
        //}
      }
      catch (SoapException sx)
      {
        string exMsg = "??";
        exMsg = sx.Detail.FirstChild.InnerText;
        throw new Exception(String.Format("ERR_line:{0}\n{1}\n{2}", errLine, errID, exMsg));
      }
      catch (Exception ex)
      {
        string exMsg = "??";
        exMsg = ex.Message;
        throw new Exception(String.Format("ErrLine:{0}\n{1}\n{2}\n{3}", errLine, errID, _crmurl, exMsg));
      }
    }


    public void SetContactAsPrimary(Guid contactID)
    {
      // Specify the database columns (entity attributes) that
      // are to be retrieved. Retrieve the parentcustomerid
      ColumnSet cols = new ColumnSet();
      //cols.Attributes = new string[] { "contactid", "fullname", "parentcustomerid" };
      cols.AddColumns(new string[] { "contactid", "fullname", "parentcustomerid" });
      // Retrieve the contact data from CRM
      contact c = (contact)_crmService.Retrieve(EntityName.contact.ToString(), contactID, cols);
      //Check if there is a parentcustomer and then check if it is an account
      if (!(c.parentcustomerid.IsNull & c.parentcustomerid.IsNullSpecified))
      {
        Guid parentID = c.parentcustomerid.Value;
        if (c.parentcustomerid.type == EntityName.account.ToString())
        {
          //Specify the database columns (entity attributes) that as need to update
          ColumnSet aCols = new ColumnSet();
          //aCols.Attributes = new string[] { "accountid", "primarycontactid" };
          aCols.AddColumns(new string[] { "accountid", "primarycontactid" });
          //Get parent account
          account a = (account)_crmService.Retrieve(EntityName.account.ToString(), parentID, aCols);
          //Set primary contact 
          a.primarycontactid = new Lookup();
          a.primarycontactid.type = EntityName.contact.ToString();
          a.primarycontactid.Value = c.contactid.Value;
          //Update account
          _crmService.Update(a);
        }
      }
    }

    //NOT TESTED THIS IS SAMPLE CODE ONLY
    public string GetNewPhone_Opp(Guid oppID)
    {
      // Specify the database columns (entity attributes) that are to be retrieved. 
      ColumnSet cols = new ColumnSet();
      cols.AddColumns(new string[] { "opportunityid", "customerid" });
      // Retrieve the contact data from CRM
      opportunity o = (opportunity)_crmService.Retrieve(EntityName.opportunity.ToString(), oppID, cols);
      if (o.customerid.type.Equals(EntityName.contact.ToString()))
      {
        Guid contactID = o.customerid.Value;
        //You now have the contactID simple call teh GetNewPhone_Contact method
        return GetNewPhone_Contact(contactID);
      }
      else if (o.customerid.type.Equals(EntityName.account.ToString()))
      {
        Guid accountID = o.customerid.Value;
        //You now have the contactID simple call teh GetNewPhone_Account method
        return GetNewPhone_Account(accountID);
      }
      else
      {
        throw new Exception("Invalid customer type!");
      }
    }


    //NOT TESTED THIS IS SAMPLE CODE ONLY
    public string GetNewPhone_OppDynamic(Guid oppID)
    {
      // Specify the database columns (entity attributes) that are to be retrieved. 
      ColumnSet cols = new ColumnSet();
      cols.AddColumns(new string[] { "opportunityid", "customerid", "primary_phone_number", "primary_contact" });
      // Retrieve the contact data from CRM

      TargetRetrieveDynamic targetRetrieve = new TargetRetrieveDynamic();
      // Set the properties of the target.
      targetRetrieve.EntityName = EntityName.opportunity.ToString();
      targetRetrieve.EntityId = oppID;
      // Create the request object.
      RetrieveRequest retrieve = new RetrieveRequest();
      // Set the properties of the request object.
      retrieve.Target = targetRetrieve;
      retrieve.ColumnSet = cols;
      // Indicate that the BusinessEntity should be retrieved as a DynamicEntity.
      retrieve.ReturnDynamicEntities = true;
      // Execute the request.
      RetrieveResponse retrieved = (RetrieveResponse)_crmService.Execute(retrieve);
      // Extract the DynamicEntity from the request.
      DynamicEntity entity = (DynamicEntity)retrieved.BusinessEntity;
      // Extract the primary contact from the dynamic entity
      // I am assuming Primary contact is a lookup field
      Lookup lookupContact = (Lookup)entity.Properties["primary_contact"];
      Guid contactID = lookupContact.Value;
      //You can get the “primary_phone_number” assuming string
      string primaryPhone = (string)entity.Properties["primary_phone_number"];
      //The trick with Dynamic entities is you have to spell the properties correctly and cast them to the correct types.
      //You now have the contactID simple call the GetNewPhone_Contact method
      return GetNewPhone_Contact(contactID);
    }


    //NOT TESTED THIS IS SAMPLE CODE ONLY
    public string GetNewPhone_Account(Guid accountID)
    {
      // Specify the database columns (entity attributes) that are to be retrieved. 
      ColumnSet cols = new ColumnSet();
      cols.AddColumns(new string[] { "accountid", "name", "telephone1", "primarycontactid" });
      // Retrieve the account data from CRM
      account a = (account)_crmService.Retrieve(EntityName.account.ToString(), accountID, cols);
      //You could now check for a primary contact and then call the GetNewPhone_Contact methor
      // or just use the account info as done here.
      //Note for an account partytype=1
      string query = String.Format(@"pId={0}&pType=1&pName={1}&partyid={0}&partytype=1&partyname={1}&partyaddressused=&contactInfo={2}", a.accountid.Value.ToString(), a.name, a.telephone1);
      UriBuilder builder = new UriBuilder(_crmServerUrl);
      if (IFD)
        builder.Path = @"/activities/phone/edit.aspx";
      else
        builder.Path = String.Format(@"/{0}/activities/phone/edit.aspx", _orgName);
      builder.Query = query;
      return builder.Uri.ToString();
    }


    public string GetNewPhone_Contact(Guid contactID)
    {
      // Specify the database columns (entity attributes) that are to be retrieved. 
      ColumnSet cols = new ColumnSet();
      //cols.Attributes = new string[] { "contactid", "fullname", "telephone1" };
      cols.AddColumns(new string[] { "contactid", "fullname", "telephone1" });
      // Retrieve the contact data from CRM
      contact c = (contact)_crmService.Retrieve(EntityName.contact.ToString(), contactID, cols);
      string query = String.Format(@"pId={0}&pType=2&pName={1}&partyid={0}&partytype=2&partyname={1}&partyaddressused=&contactInfo={2}", c.contactid.Value.ToString(), c.fullname, c.telephone1);
      UriBuilder builder = new UriBuilder(_crmServerUrl);
      if (IFD)
        builder.Path = @"/activities/phone/edit.aspx";
      else
        builder.Path = String.Format(@"/{0}/activities/phone/edit.aspx", _orgName);
      builder.Query = query;
      return builder.Uri.ToString();
    }

    public string GetNewTask_Contact(Guid contactID)
    {
      // Specify the database columns (entity attributes) that are to be retrieved. 
      ColumnSet cols = new ColumnSet();
      //      cols.Attributes = new string[] { "contactid", "fullname" };
      cols.AddColumns(new string[] { "contactid", "fullname" });
      // Retrieve the contact data from CRM
      contact c = (contact)_crmService.Retrieve(EntityName.contact.ToString(), contactID, cols);
      string query = String.Format(@"pId={0}&pType=2&pName={1}", c.contactid.Value.ToString(), c.fullname);
      UriBuilder builder = new UriBuilder(_crmServerUrl);
      if (IFD)
        builder.Path = @"/activities/task/edit.aspx";
      else
        builder.Path = String.Format(@"/{0}/activities/task/edit.aspx", _orgName);
      builder.Query = query;
      return builder.Uri.ToString();
    }

    public string GetNewEmail_Contact(Guid contactID)
    {
      // Specify the database columns (entity attributes) that are to be retrieved. 
      ColumnSet cols = new ColumnSet();
      //cols.Attributes = new string[] { "contactid", "fullname" };
      cols.AddColumns(new string[] { "contactid", "fullname" });
      // Retrieve the contact data from CRM
      contact c = (contact)_crmService.Retrieve(EntityName.contact.ToString(), contactID, cols);
      string query = String.Format(@"pId={0}&pType=2&pName={1}&partyid={0}&partytype=2&partyname={1}", c.contactid.Value.ToString(), c.fullname);
      UriBuilder builder = new UriBuilder(_crmServerUrl);
      if (IFD)
        builder.Path = @"/activities/email/edit.aspx";
      else
        builder.Path = String.Format(@"/{0}/activities/email/edit.aspx", _orgName);
      builder.Query = query;
      return builder.Uri.ToString();
    }

    public string GetNewCase_Contact(Guid contactID)
    {
      string query = String.Format(@"_CreateFromType=2&_CreateFromId={0}", contactID);
      UriBuilder builder = new UriBuilder(_crmServerUrl);
      if (IFD)
        builder.Path = @"/cs/cases/edit.aspx";
      else
        builder.Path = String.Format(@"/{0}/cs/cases/edit.aspx", _orgName);
      builder.Query = query;
      return builder.Uri.ToString();
    }
  }
}